iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
自我挑戰組

JavaScript 是什麼?可以吃嗎?系列 第 3

事件迴圈(Event Loop)- 下集

  • 分享至 

  • xImage
  •  

嗨大家好,我是Eric,在上集中,我們講了瀏覽器有多個進程和線程,以及渲染主線程(Main Thread in Renderer Process)有多麼的忙碌。

今天我們來深入探討事件迴圈(Event Loop)是如何幫助主線程有效地處理這一堆任務。

事件迴圈:主線程的好幫手

事件迴圈就像廚師的助手,幫忙看著「訂單(任務)」是不是已經做好了。簡單來說,它會一直檢查有沒有新任務要處理,有就拿來做,沒有就稍等一會。

// 簡單範例
while(true) {
  let task = messageQueue.shift();
  if(task) {
    execute(task);
  }
}

任務有優先順序嗎?

消息隊列就像廚房裡的訂單,先來的先做(FIFO,First-In-First-Out),但是瀏覽器有多個不同類型的隊列,像是微任務隊列(Microtask Queue)和宏任務隊列(Macrotask Queue),而有些訂單(微任務)比較急,所以會優先處理。。

延遲隊列:用於儲存計時器到達後的回調任務,優先級「中」(Delay Queue)
交互隊列:用於儲存用戶操作後產生的事件處理任務,優先級「高」(Interaction Queue)
微隊列:用於儲存需要最快執行的任務,優先級「最高」(Microtask Queue)

// Promise 是個急迫的客人(微任務)
Promise.resolve().then(() => {
  console.log("這個訂單很急!");
});

// setTimeout 是比較悠閒的客人(延遲隊列)
setTimeout(() => {
  console.log("這個訂單可以等等!");
}, 0);

為什麼不多請幾個廚師(多線程)?

可能有人會問,為什麼不用多個線程來同時執行這些任務呢?其實,JavaScript 是單線程的,這意味著一次只能執行一個任務。如果兩個線程同時改變 DOM 或其他共享資源,那可能會引發一些很嚴重的問題(比如資料不一致)。

異步(Asynchronous):主線程的救星

在上面的介紹中,我們講到了許多關於事件迴圈(Event Loop)的核心概念。但是,還有一個非常重要的主題需要討論,那就是「異步(Asynchronous)」。

在JavaScript世界中,異步不等於多線程。JavaScript 是單線程的,這意味著一次只能做一件事。但是,異步操作允許我們避免阻塞這個單一的線程。

比如,當你使用 fetch() 函數去獲取一些遠程資料時,JavaScript 會將這個任務交給瀏覽器的其他部分(可能是Web API或是瀏覽器的其他線程)來處理,然後它會繼續執行下面的程式碼,不會等待 fetch() 的完成。

如果使用同步的方式,就極有可能導致主線程產生阻塞,從而導致消息隊列中的很多其他任務無法得到執行。這樣一來,一方面會導致繁忙的主線程白白地消耗時間,另一方面導致頁面無法及時更新,給 User 造成卡死現象。

// 異步操作示例
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
  
console.log('我不會等 fetch 完成');

結論

了解事件迴圈(Event Loop)對於優化你的網站和提供更好的用戶體驗是非常重要的。只有明白了這些底層的運作原理,我們才能寫出更高效、更流暢的網頁。
希望這個介紹能幫助大家更好地理解事件迴圈(Event Loop)和它在前端開發中的重要性!謝謝大家~~~明天見!

參考資料:W3C HTML Spec - Event Loop


上一篇
事件迴圈(Event Loop)- 上集
下一篇
Day4 - 瀏覽器渲染原理解析
系列文
JavaScript 是什麼?可以吃嗎?20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言